import React, { forwardRef, useEffect, useImperativeHandle, useState, useMemo } from 'react'
import { Button, Form, Space } from 'antd'

const MyForm = forwardRef(({ initValues, config, list, buttons }, ref) => {
  const [form] = Form.useForm()
  const [initialValues, setInitialValues] = useState(undefined)
  useImperativeHandle(ref, () => {
    return {
      ...form,
      forceUpdate,
      reset
    }
  })
  useEffect(() => {
    if (typeof initValues === 'string') {
      window.$api[initValues]().then(res => {
        setInitialValues(() => res)
      })
    }
    if (Object.prototype.toString.call(initValues) ==='[object Object]') {
      setInitialValues(() => initValues)
    }
  }, [])
  useEffect(() => {
    if (initialValues) {
      reset()
    }
  }, [initialValues])
  const [formVersion, setFormVersion] = useState(0) // 用于监听formData变化，更新disable或者其它
  const forceUpdate = () => {
    setFormVersion(v => v + 1)
  }
  const reset = () => {
    Object.keys(form.getFieldsValue()).forEach(key => {
      if (initialValues && initialValues[key]) {
        form.setFieldValue(key, initialValues[key])
      } else {
        form.setFieldValue(key, undefined)
      }
    })
    forceUpdate()
  }
  const onValuesChange = (changedValues, allValues) => {
    forceUpdate()
  }

  // 优化渲染性能
  const FormItems = useMemo(() => {
    return (list ?? []).map(({ bind, Component, ...restItem }) => {
      // 常用的两个可以联动的属性抽出来做动态
      const disabled = typeof bind.disabled === 'function' ? bind.disabled(form) : bind.disabled
      const allowClear = typeof bind.allowClear === 'function' ? bind.allowClear(form) : bind.allowClear
      return (
        <Form.Item style={{ marginBottom: '8px' }} {...restItem} key={restItem.name}>
          <Component
            name={restItem.name}
            parent={form}
            style={{ width: '100%' }}
            {...bind}
            disabled={disabled}
            allowClear={allowClear}
          />
        </Form.Item>
      )
    })
  }, [formVersion])
  const ButtonItems = useMemo(() => (buttons ?? []).map((attrs) => {
    return (
      <Button
        {...attrs}
        key={attrs.key}
      >
        {attrs.text}
      </Button>
    )
  }), [buttons])
  return (
    <Form
      className="form-component"
      layout="inline"
      autoComplete="off"
      labelWrap
      initialValues={initialValues}
      form={form}
      size="small"
      onValuesChange={onValuesChange}
      { ...config }>
      { FormItems }
      <Form.Item colon={false} label={" "}>
        <Space>
          { ButtonItems }
        </Space>
      </Form.Item>
    </Form>
  )
})

export default MyForm
